// 观察者
class Listener{
    // 事件（消息）名称
    private _event:string = 'event';
    // 消息对应的回调函数
    private _callback:Function = null;
    // 回调函数的this指向  （如果是箭头函数，则可以不传值进来）
    private _target = null;
    // 构造函数
    constructor(event:string,callback:Function,target?){
        this._event = event;
        this._callback = callback;
        this._target = target;
    }
    // 获取回调函数的接口
    get CallBack(){
        return this._callback;
    }
    // 获取事件名称
    get EventType(){
        return this._event;
    }
    // 执行回调函数
    callEvent(...args){
        // 通过apply锁定this指向，并传递参数列表
        this._callback.apply(this._target,[...args]);
    }

}

// 事件管理者 - 消息中心
export class EventManager{
    // 存储观察者的容器
    private _listeners:Array<Listener> = new Array();

    // 单例
    private static _instance:EventManager = null;
    private constructo(){}
    static get Instance(){
        this._instance = this._instance || new EventManager();
        return this._instance;
    }


    // 添加事件
    addEvent(event:string,callback:Function,target?){
        // 创建观察者 绑定事件名称 回调及函数环境
        const listener = new Listener(event,callback,target);
        // 存储观察者
        this._listeners.push(listener);
    }
    // 激活事件  发送消息  携带不定数量的参数
    dispatcher(event:string,...args){
        // 遍历容器 查找对应的观察者  可能找到多个相同事件名称的观察者
        for (const listener of this._listeners) {
            // 找到对应观察者 
            if (listener.EventType === event) {
                // 观察者执行自己保存的回调函数 并传递参数列表
                listener.callEvent(...args);
            }
        }
    }
    // 移除事件
    removeEvent(event:string|Function){
        // 参数是消息则通过消息 移除所有对应的观察者
        if (typeof(event) === 'string') {
            this.removeListener(event);
            return;
        }
        // 参数是函数 则移除这一个观察者
        this.removeCallBack(event);
    }

    // 通过函数移除一个观察者
    private removeCallBack(callback:Function){
        // 遍历数组 
        for (let i = 0; i < this._listeners.length; i++) {
            const listener = this._listeners[i];
            // 比对函数的地址 相同 则移除这个观察者
            if (listener.CallBack === callback) {
                this._listeners.splice(i,1);
                return;
            }
        }  
    }
    // 通过消息移除观察者
    private removeListener(event:string){
         // 遍历数组
        for (let i = 0;i < this._listeners.length; i++) {
            const listener = this._listeners[i];
             // 比对消息名称 相同 则移除这些观察者
            if (listener.EventType === event) {
                this._listeners.splice(i--,1);
            }
        }
    }

    // 清空观察者
    removeAll(){
        this._listeners = [];
    }

}